#!/usr/bin/env python2
# -*- coding: utf-8 -*-

import os
import re
import web
import json
import time
import traceback

from sqlalchemy.orm.exc import NoResultFound
from Umpweb.base import render_jinja
from Umpweb.db import api as db_api
from Umpweb.common import utils, config
from Umpweb.base import session, _, render_jinja
from Umpweb.common.utils import login_required


urls = ( 
        '/list',            'VolumeList',
        '/grid',            'GridVolume',
        '/create',          'VolumeCreate',
        '/update',          'VolumeUpdate',
        '/delete',          'VolumeDelete',
        '/expunge',         'VolumeExpunge',
        '/restore',         'VolumeRestore',
        '/flatten',         'VolumeFlatten',
        '/copy',            'VolumeCopy',
        '/get_used',        'GetVolumeUsed',
)

app = web.application(urls, locals())
render = render_jinja('static/templates/volume', encoding='utf-8',)

class VolumeList:
    @login_required
    def GET(self):
        web.header("Content-Type", "text/plain")
        pools = db_api.pool_get_all()
        reload(config)
        protocols = config.protocols
        return render.volume_list(pools=pools, protocols=protocols)


VOLUME_STAT_MAP = {
    '' : '正常',
    'normal': '正常',
    'copying': '拷贝中',
    'creating': '创建中',
    'fail': '预分配失败',
    'waiting': '等待创建',
}

VOLUME_PRIORITY_MAP = {
    '0': '高速层',
    '1': '低速层',
    '-1': '自动分层'
}

class GridVolume:
    def POST(self):
        web_input = web.input()

        is_target = 't_id' in web_input.keys()
        fake_deleted = web_input.get('fake_deleted')
        fake_deleted = fake_deleted == 'true'
        filters = {'fake_deleted':fake_deleted}

        if is_target :
            t_id = web_input['t_id']
            if t_id != 'all':
                filters['pool_id'] = t_id
        protocol = web_input.get('protocol')
        if protocol:
            filters['protocol'] = protocol

        page, total, records, rows = \
                utils.grid_rows_query(db_api.volume_table, web_input, filters=filters)

        for volume in rows:
            if volume is not None:
                pool = db_api.pool_get(volume.pool_id)
                volume.lun_path = "%s.%s"%(pool.name, volume.name)
            if volume.protocol != 'iscsi':
                volume.iqn = ''
            iops = db_api.volume_iops_get_with_volume(volume.id)
            iops_ = iops_read = iops_write = swallow_spit = spit =  swallow = 0
            if iops:
                iops_, iops_read, iops_write= iops._iops, iops._read, iops._write
                swallow_spit, spit, swallow = iops._in_out, iops._out, iops._in

            # volume.IOPS = '<span style="display:block;text-align:center">r：%s，w：%s</span>' % (iops_read, iops_write)
            # volume.swallow = '<span style="display:block;text-align:center">in：%s，out：%s</span>' % (swallow, spit)
            volume.IOPS = 'r：%s，w：%s' % (iops_read, iops_write)
            volume.swallow = 'in：%s，out：%s' % (swallow, spit)

            volume.status_ = VOLUME_STAT_MAP.get(volume.status, 'flattening')

            if volume.provisioning == 'thick':
                volume.provisioning_ = '非精简'
            else:
                volume.provisioning_ = '精简'
            volume.protocol_show = volume.protocol.upper()
            if volume.protocol == 'iscsi':
                volume.protocol_show = 'iSCSI'
            if volume.protection_domain_id:
                protection_domain = db_api.protection_domain_get(volume.protection_domain_id)
                volume.protection_domain = protection_domain.name

            volume.priority_show = VOLUME_PRIORITY_MAP.get(volume.priority, volume.priority)

            vgroup = db_api.vgroup_get(volume.vgroup_id)
            volume.vgroup = vgroup.name if vgroup else ''
            snapshot = db_api.snapshot_get(volume.snapshot_id)
            if snapshot:
                volume.fromsnap = snapshot.path
            if volume.size:
                volume.size_gb = int(utils.byte2GB(volume.size, 1000))
            
            sum_list = lambda x, y : x + y

            volume.analysis_latency_show = '已关闭' 
            if volume.analysis_latency:
                volume.analysis_latency_show = '已开启' 

        cells = ['id', 'path', 'iqn', 'protocol_show', 'lun_path', 'status',
                'status_', 'provisioning_', 'size_gb','used_gb', 'IOPS','swallow',
                'connection_show', 'protection_domain', 'vgroup', 'clone_type', 
                'fromsnap','snapshot_id', 'analysis_latency_show', 'priority_show', 'username',
                'created_at','mount', 'path']

        rows_json = utils.grid_json(
                page, total, records, rows, 'id', cells)
        web.header("Content-Type", "application/json")
        return rows_json


class GetVolumeUsed:
    def GET(self):
        webdata = web.input()
        web.header("Content-Type", "application/json")
        ids_str = webdata['ids']
        volume_ids = ids_str.split(',')
        res = []
        volume_ids = [vid for vid in volume_ids if vid]
        for volume_id in volume_ids:
            values = {'id':volume_id}
            body = {"VolumeGetUsed":{'params':values}}
            reply = web.config._server.api_sync_call(body)
            volume = db_api.volume_get(volume_id)
            if volume:
                res.append(str(volume.used_gb))
        return json.dumps(res)


class VolumeCreate:
    @login_required
    def GET(self):
        x = web.input()
        pool_id = x.get('pool_id')
        pool = None
        protection_domains = []
        if pool_id:
            pool = db_api.pool_get(pool_id)
            protection_domains = db_api.protection_domain_get_with_pool(pool_id)
        if not protection_domains:
            protection_domains = db_api.protection_domain_get_all()
        is_showPool = config.is_showPool
        pools = db_api.pool_get_all()
        isolations = db_api.access_control_get_all()
        qoses = db_api.qos_get_all()
        reload(config)
        protocols = config.protocols
        
        snappolicy = db_api.snappolicy_get_all()
        return render.volume_create(pools=pools,\
                                    pool = pool,
                                    snappolicy = snappolicy,
                                    protocols=protocols,\
                                    protection_domains=protection_domains,\
                                    is_showPool=is_showPool,\
                                    qoses =qoses,
                                    isolations=isolations)

    def POST(self):
        web.header("Content-Type", "application/json")
        x = web.input()
        pool_id = x.get('pool_id','').strip()
        isCreatePool = False
        if not config.is_showPool:
            pool_id = None
            isCreatePool = True
        pool = db_api.pool_get(pool_id)
        values = dict(**x)

        values['protocol'] = pool.protocol
        values['size'] = int(x.size_gb.strip()) * 1000 * 1000 * 1000

        body = {"VolumeCreate":{'params':values}}
        return utils.web_return(body)


# class Volume_confirm_delete:
#     @login_required
#     def GET(self, id):
#         web.header("Content-Type", "text/plain")
#         return render.volume_confirm_delete()


class VolumeDelete(object):
    @login_required
    def GET(self):
        x = web.input()
        x.update(fake_delete=True)
        web.header("Content-Type", "application/json")
        values = dict(**x)
        body = {"VolumeDelete": {'params': values}}
        return utils.web_return(body)


class VolumeExpunge(object):
    @login_required
    def GET(self):
        x = web.input()
        web.header("Content-Type", "application/json")

        values = dict(**x)
        body = {"VolumeExpunge": {'params': values}}
        return utils.web_return(body)


class VolumeRestore(object):
    @login_required
    def GET(self):
        x = web.input()
        web.header("Content-Type", "application/json")

        values = dict(**x)
        body = {"VolumeRestore": {'params': values}}
        return utils.web_return(body)


class VolumeFlatten:
    @login_required
    def GET(self):
        x = web.input()
        web.header("Content-Type", "application/json")
        values = dict(**x)
        body = {"VolumeFlatten":{'params':values}}
        return utils.web_return(body)


class VolumeCopy:
    
    def GET(self):
        x = web.input()
        pools = db_api.pool_get_with_user(web.config._session.user.id)
        if db_api.check_is_adminstrator(web.config._session.user.name):
            pools = db_api.pool_get_all()
        volume = db_api.volume_get(x.get('id'))
        pool = db_api.pool_get(volume.pool_id)
        volume.pool = pool
        return render.volume_copy(volume=volume, pools=pools, pool=pool)

    def POST(self): 
        web.header("Content-Type", "application/json")
        x = web.input()
        volume_name = x['tgt_volume']
        priority = x['priority']

        pool2 = db_api.pool_get(x.get('pool_id'))
        name2 = "%s/%s" % (pool2.name, volume_name)

        volume = db_api.volume_get(x.get('volume_id'))
        pool = db_api.pool_get(volume.pool_id)
        name = "%s/%s" % (pool.name, volume.name)
         
        values = {
            'name2': name2, 
            'owner2': pool2.username,
            'protocol2': pool2.protocol,
            'protocol': volume.protocol, 
            'name': name,
            'priority':priority,
            'owner': volume.username
        }

        body = {"VolumeCopy":{'params':values}}
        rsp = utils.web_return(body)
        return rsp 


class VolumeUpdate:
    @login_required
    def GET(self):
        x = web.input()
        volume = db_api.volume_get(x['id'])

        isolations = db_api.access_control_get_all()
        qoses = db_api.qos_get_all()
        if volume.access_policy_id:
            volume.access_policy = db_api.access_control_get(volume.access_policy_id)
        if volume.qos_id:
            volume.qos = db_api.qos_get(volume.qos_id)
        snappolicies = db_api.snappolicy_get_with_volume(volume.id)
        volume.snappolicies = snappolicies
        if volume.size:
                volume.size_gb = int(utils.byte2GB(volume.size, 1000))
        snappolicy = db_api.snappolicy_get_all()
        pool = db_api.pool_get(volume.pool_id)
        return render.volume_update(
                pool = pool,
                snappolicy = snappolicy,
                qoses =qoses,
                isolations=isolations,
                volume = volume)

    def POST(self):
        web.header("Content-Type", "application/json")
        x = web.input()
        values = dict(**x)
        values['size'] = int(x.size_gb.strip()) * 1000 * 1000 * 1000
        body = {"VolumeUpdate":{'params':values}}
        return utils.web_return(body)
